/**
 * Create by 少凡
 * 2018/6/12
 */
import {Injectable} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {TreeNodeInterface} from '../interface/TreeNodeInterface';
import {Data} from '@angular/router';
import {Observable, Observer} from 'rxjs';

let moment = require('moment');


@Injectable({
  providedIn: 'root'
})
export class ZorroService {

  //+号 可展开表格集合
  expandSet = new Set<number>();
  //复选框表格集合
  setOfCheckedId = new Set<number>();
  // 当前页的数据
  listOfCurrentPageData: ReadonlyArray<Data> = [];
  // 选中
  checked = false;
  // 全选、半全选
  indeterminate = false;


  constructor() {
  }

  /**
   * 树型表格---开始------↓
   * @param root
   */
  convertTreeToList(root: object): TreeNodeInterface[] {
    const stack: any[] = [];
    const array: any[] = [];
    const hashMap = {};
    stack.push({...root, level: 0, expand: false});

    while (stack.length !== 0) {
      const node = stack.pop();
      this.visitNode(node, hashMap, array);
      if (node.children) {
        for (let i = node.children.length - 1; i >= 0; i--) {
          stack.push({...node.children[i], level: node.level + 1, expand: false, parent: node});
        }
      }
    }
    return array;
  }

  ////树型表格，将数据转换为树型
  visitNode(node: TreeNodeInterface, hashMap: { [key: string]: any }, array: TreeNodeInterface[]): void {
    if (!hashMap[node.key]) {
      hashMap[node.key] = true;
      array.push(node);
    }
  }

  //树型表格，展开下级
  collapse(array: TreeNodeInterface[], data: TreeNodeInterface, $event: boolean): void {
    if ($event === false) {
      if (data.children) {
        data.children.forEach(d => {
          const target = array.find(a => a.key === d.key)!;
          target.expand = false;
          this.collapse(array, target, false);
        });
      } else {
        return;
      }
    }
  }

  /**
   * 树型表格---结束------↑
   */

  /**
   * +号可展开表格---开始------↓
   * @param id
   * @param checked
   */
  onExpandChange(id: number, checked: boolean): void {
    if (checked) {
      this.expandSet.add(id);
    } else {
      this.expandSet.delete(id);
    }
  }

  /**
   * +号可展开表格---结束------↑
   */

  /**
   * 带选择框表格---开始------↓
   * @param id
   * @param checked
   */
  // 单个多选框选中、不选
  onItemChecked(id: number, checked: boolean): void {
    this.updateCheckedSet(id, checked);
    this.refreshCheckedStatus();
  }

  // 选中集合的增删
  updateCheckedSet(id: number, checked: boolean): void {
    if (checked) {
      this.setOfCheckedId.add(id);
    } else {
      this.setOfCheckedId.delete(id);
    }
  }

  // 刷新全选框的状态，看是否半选还是全选
  refreshCheckedStatus(): void {
    const listOfEnabledData = this.listOfCurrentPageData.filter(({disabled}) => !disabled);
    this.checked = listOfEnabledData.every(({id}) => this.setOfCheckedId.has(id));
    this.indeterminate = listOfEnabledData.some(({id}) => this.setOfCheckedId.has(id)) && !this.checked;
  }

  // 多选框全选
  onAllChecked(checked: boolean): void {
    this.listOfCurrentPageData.filter(({disabled}) => !disabled).forEach(({id}) => this.updateCheckedSet(id, checked));
    this.refreshCheckedStatus();
  }

  /**
   * 带选择框表格---结束------↑
   */


  /**
   * 替换数组值  如果索引值有问题 那么返回null
   * @param data 数组
   * @param index 索引 你要替换那个索引值
   * @param value 你要替换的值
   * */
  arrayExchangeValue(data: any, index: any, value: any) {
    if (data == null) {
      return data;
    }
    let value1 = data[index];
    if (data[index] == null) {
      return data;
    }
    data[index] = value;
    data[index + 1] = value1;
    return data;
  }

  nowdate: Date = new Date();
  //默认今天的日期
  startDate: Date = new Date(this.nowdate.getTime() - this.nowdate.getHours() * 1000 * 60 * 60 - this.nowdate.getMinutes() * 1000 * 60 - this.nowdate.getSeconds() * 1000);
  //默认今天结束的日期
  endDate: Date = new Date(this.nowdate.getTime() - this.nowdate.getHours() * 1000 * 60 * 60 - this.nowdate.getMinutes() * 1000 * 60 - this.nowdate.getSeconds() * 1000 - 1000 + 24 * 60 * 60 * 1000);

  /**
   * 获得本周时间差
   * callback 回调参数
   * dateTime 是否自己传递参数 传递参数建议传递开始时间
   * */
  getDateTime(dateTime?) {
    let now;
    if (dateTime == null) {
      now = new Date(); //当前日期
    } else {
      now = dateTime; //当前日期
    }
    let nowDayOfWeek = now.getDay(); //今天本周的第几天
    let nowDay = now.getDate(); //当前日
    let nowMonth = now.getMonth(); //当前月
    let nowYear = now.getFullYear(); //当前年
    nowYear += (nowYear < 2000) ? 1900 : 0;

    /** 上个月开始 */
    let startLastMonth = new Date(nowYear, nowMonth - 1);
    /** 上个月结束 */
    let endLastMonth = new Date(nowYear, nowMonth, 0, +'23', +'59', +'59');
    /** 今天*/
    let todayStart = new Date(nowYear, nowMonth, nowDay);
    /** 今天结束*/
    let todayEnd = new Date(nowYear, nowMonth, nowDay, +'23', +'59', +'59');
    /** 昨天*/
    let yesterdayStart = new Date(nowYear, nowMonth, nowDay - 1);
    /** 昨天结束*/
    let yesterdayEnd = new Date(nowYear, nowMonth, nowDay - 1, +'23', +'59', +'59');
    /** 获得本周的开始日期     获取周一 */
    let weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
    /** 本周日的日期   获取当前日期 */
    now.setDate(now.getDate() + 6);
    let weekEndDate = new Date(nowYear, nowMonth, nowDay + (7 - nowDayOfWeek), +'23', +'59', +'59');
    /** 半年前*/
    let sixMonthsAgo = new Date(nowYear, nowMonth - 6, nowDay);
    /** 3个月前*/
    let threeMonthsAgo = new Date(nowYear, nowMonth - 3, nowDay);
    /** 1个月前*/
    let oneMonthsAgo = new Date(nowYear, nowMonth - 1, nowDay);
    return {
      /** 昨天开始 */
      startYesterday: yesterdayStart,
      /** 昨天结束 */
      endYesterday: yesterdayEnd,
      /** 今天*/
      startToday: todayStart,
      /** 今天结束*/
      endToday: todayEnd,
      /** 这周开始时间*/
      startWeek: weekStartDate,
      /** 这周结束时间*/
      endWeek: weekEndDate,
      // /** 这个月开始时间*/
      // startOfMonth:startOfMonth(now),
      // /** 这个月结束时间*/
      // endOfMonth:endOfMonth(now),
      startOfMonth: new Date(moment().startOf('month').valueOf()),
      // endOfMonth: new Date(moment().endOf('month').valueOf()),
      endOfMonth: new Date(),

      /** 上个月开始 */
      startLastMonth: startLastMonth,
      /** 上个月结束 */
      endLastMonth: endLastMonth,

      endTime: new Date(nowYear, nowMonth, nowDay - 31),
      //   lastMonthStart: new Date(moment().month(moment().month() - 1).startOf('month').valueOf()),
      // lastMonthEnd: new Date(moment().month(moment().month() - 1).endOf('month').valueOf()),
      /** 半年前*/
      sixMonthsAgo: sixMonthsAgo,
      /** 3个月前*/
      threeMonthsAgo: threeMonthsAgo,
      /** 1个月前*/
      oneMonthsAgo: oneMonthsAgo,
    };
  }

  /**
   * 跟格式返回格式化的日期时间
   */
  getFormatDateTime(dateTime, format) {

    let year = dateTime.getFullYear(); //当前年
    let month = dateTime.getMonth() + 1;//当前月
    let day = dateTime.getDate(); //当前日
    let hours = dateTime.getHours() != 0 ? dateTime.getHours() : '00'; // 当前小时
    let minutes = dateTime.getMinutes() != 0 ? dateTime.getMinutes() : '00'; // 当前分钟
    let seconds = dateTime.getSeconds() != 0 ? dateTime.getSeconds() : '00'; // 当前秒

    let formatDateTime = '';

    /** 获得yyyy-MM-dd HH:mm:ss格式化后的日期时间 */
    if ('yyyy-MM-dd HH:mm:ss' == format) {
      formatDateTime = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
    }

    if ('HH:mm:ss' == format) {
      formatDateTime = hours + ':' + minutes + ':' + seconds;
    }

    return formatDateTime;
  }

  /**
   * 表单的验证
   * @param data
   */
  validateFormValidate(validateForm: FormGroup): boolean {
    let validate = true;
    for (const i in validateForm.controls) {
      if (!validateForm.controls[i].valid) {
        validate = false;
      }
      validateForm.controls[i].markAsDirty();
      validateForm.controls[i].updateValueAndValidity();
    }
    return validate;
  }

  /**
   * 清空所有表单的报错提示 不包括自定义！
   */
  clearFormError(validateForm: FormGroup) {
    for (const i in validateForm.controls) {
      validateForm.controls[i]!.markAsPristine();
      validateForm.controls[i]!.updateValueAndValidity();
    }
  }

  /***
   * 清空所以表单的值
   * @param validateForm
   */
  clearFormVaildate(validateForm: FormGroup) {
    for (const i in validateForm.controls) {
      validateForm.controls[i].setValue('');
      validateForm.controls[i].updateValueAndValidity();
    }
  }


  // /**
  //  * 图片压缩 压缩图片
  //  * */
  imgUpload(file: any) {
    return new Observable((observer: Observer<Blob>) => {
      const reader = new FileReader();
      // tslint:disable-next-line:no-any
      reader.readAsDataURL(file as any);
      reader.onload = (fileInfo) => {
        // 创建图片对象
        const imageElement = new Image();
        // 图片上传地址 fileInfo
        if (typeof fileInfo.target.result === 'string') {
          // 改变图片的src
          imageElement.src = fileInfo.target.result;
        }
        // 必须要放在onload方法里面
        imageElement.onload = () => {
          // 图片原始尺寸
          const originWidth = imageElement.width;
          const originHeight = imageElement.height;
          // 最大尺寸限制
          const maxWidth = 1280, maxHeight = 1028;
          // 目标尺寸
          let targetWidth = originWidth, targetHeight = originHeight;
          // 图片尺寸超过750x400的限制
          if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
              // 更宽，按照宽度限定尺寸
              targetWidth = maxWidth;
              targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
              targetHeight = maxHeight;
              targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
          }
          const canvas = document.createElement('canvas');
          const img = document.createElement('img');
          img.src = reader.result as string;
          img.onload = () => {
            const ctx = canvas.getContext('2d')!;
            // canvas对图片进行缩放
            canvas.width = targetWidth;
            canvas.height = targetHeight;
            // 清除画布
            ctx.clearRect(0, 0, targetWidth, targetHeight);
            // 可以增加水印功能 比较麻烦
            // ctx.fillStyle = 'red';
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
            // 如果对这个方法有问题建议直接看官方文档 百度乱得要死
            // https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
            canvas.toBlob(blob => {
              observer.next(blob!);
              observer.complete();
            }, 'image/jpeg', 0.7);
          };
        };
      };
    });
  }

}
